package traverse;

import java.util.HashSet;
import java.util.Set;

public class TwentyFourPoint {
    //结果集合
    private Set<String> answerList = new HashSet<>();

    public TwentyFourPoint() {
    }

    public static class Solution {
        public float[] cardArr;//扑克牌（防止除法小数计算导致计算不准确）
        public String expStr = "";//数学算式
        public String[] strings;//扑克牌string类型

        public Solution() {
        }

        public Solution(int cardArr[]) {
            this.cardArr = new float[]{cardArr[0], cardArr[1], cardArr[2], cardArr[3]};
            this.strings = new String[]{cardArr[0] + "", cardArr[1] + "", cardArr[2] + "", cardArr[3] + ""};//将扑克牌转换成string类型
        }
    }

    public void count(Solution solution) {
        float[] arr = solution.cardArr;
        //递归停止条件
        if (arr.length <= 1) {
            //找到解决方案（数组中只剩下一个数并且等于24）
            if (arr.length == 1 && arr[0] == 24) {
                //去掉最外层括号
                answerList.add(solution.expStr.substring(1, solution.expStr.length() - 1));
            }
            return;
        }

        //每两个数进行运算
        for (int i = 0;i < arr.length - 1; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                float card1 = arr[i];
                float card2 = arr[j];

                String cardStr1 = solution.strings[i];
                String cardStr2 = solution.strings[j];

                //两个数之间的运算规则（+：1，-：2，*：1，/：2）
                for (int k = 0; k < 6; k++) {
                    Solution newSolution = getNewSolution(solution, i);
                    //将计算好的数添加到新的Solution中去
                    switch (k) {
                        case 0://加法card1+card2
                            newSolution.cardArr[j - 1] = card1 + card2;
                            newSolution.expStr = cardStr1 + "+" + cardStr2;
                            break;
                        case 1://card1-card2
                            newSolution.cardArr[j - 1] = card1 - card2;
                            newSolution.expStr = cardStr1 + "-" + cardStr2;
                            break;
                        case 2://card2-card1
                            newSolution.cardArr[j - 1] = card2 - card1;
                            newSolution.expStr = cardStr2 + "-" + cardStr1;
                            break;
                        case 3://乘法card1*card2
                            newSolution.cardArr[j - 1] = card1 * card2;
                            newSolution.expStr = cardStr1 + "*" + cardStr2;
                            break;
                        case 4://card1/card2
                            //card2不为零，分母
                            if (card2 != 0) {
                                newSolution.cardArr[j - 1] = card1 / card2;
                                newSolution.expStr = cardStr1 + "/" + cardStr2;
                            } else {
                                continue;
                            }
                            break;
                        case 5://card2/card1
                            //card1不为零，分母
                            if (card1 != 0) {
                                newSolution.cardArr[j - 1] = card2 / card1;
                                newSolution.expStr = cardStr2 + "/" + cardStr1;
                            } else {
                                continue;
                            }
                            break;
                    }
                    newSolution.expStr = "(" + newSolution.expStr + ")";//两个数的结果当做一个进行下一次递归运算
                    newSolution.strings[j - 1] = newSolution.expStr;
                    //递归调用
                    count(newSolution);
                }
            }
        }
    }

    private static Solution getNewSolution(Solution solution, int i) {
        Solution newSolution = new Solution();
        newSolution.expStr = solution.expStr;
        newSolution.cardArr = new float[solution.cardArr.length - 1];
        newSolution.strings = new String[solution.cardArr.length - 1];

        //去除第i个元素构造新的数组
        for (int m = 0, n = 0; m < solution.cardArr.length; m++) {
            if (m != i) {
                newSolution.cardArr[n] = solution.cardArr[m];
                newSolution.strings[n] = solution.strings[m];
                n++;
            }
        }
        return newSolution;
    }

    public Set<String> getAnswerList() {
        return answerList;
    }
}
